package com.xncoding.jwt.controller;

import com.xncoding.jwt.commons.SocketConstants;
import com.xncoding.jwt.config.WebSocketConfigProperties;
import com.xncoding.jwt.handler.SocketUsersHandler;
import com.xncoding.jwt.model.RequestMessage;
import com.xncoding.jwt.model.ResponseMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * WsController
 *
 * @author XiongNeng
 * @version 1.0
 * @since 2018/2/28
 */
@Controller
@Slf4j
public class WsController {

    private final SimpMessagingTemplate messagingTemplate;


    /***
     * socket会话配置类
     */
    private final WebSocketConfigProperties socketConfigProperties;

    @Autowired
    public WsController(SimpMessagingTemplate messagingTemplate, WebSocketConfigProperties socketConfigProperties) {
        this.messagingTemplate = messagingTemplate;
        this.socketConfigProperties = socketConfigProperties;
    }

    /***
     * <p>
     *     @MessageMapping("/welcome")： 这个注解用于指定一个方法作为WebSocket客户端发送到服务器的消息处理器。
     *     当WebSocket客户端向服务器发送一个消息到/welcome的地址时，
     *     这个方法会被调用。这里的/welcome是消息的映射路径，相当于HTTP中的URL路径，用于区分不同的消息类型。
     * </p>
     *
     * <p>
     *     @SendTo("/topic/say")： 这个注解用于指示处理完@MessageMapping指定的方法后，
     *     服务器应该将结果广播到哪个目的地。/topic/say是目的地的路径，这里的/topic前缀表明这是一个主题（Topic）订阅，
     *     而不是直接的点对点（Point-to-Point）通信。这意味着，
     *     当处理方法执行完毕后，其返回值会被发送到/topic/say这个主题，所有订阅了这个主题的WebSocket客户端都会收到这个消息。
     * </p>
     * @param message
     * @return
     */
    @MessageMapping("/welcome")
    @SendTo("/topic/say")
    public ResponseMessage say(RequestMessage message) {
        System.out.println(message.getName());
        return new ResponseMessage("welcome," + message.getName() + " !");
    }

    /***
     * 给指定在线用户基于webSocket发送实时消息
     *
     * @param receiveUserId 接受用户的id
     * @param message 发送消息内容
     * @author feilong
     * @version 1.0
     */
    @GetMapping("/sendMessage")
    @ResponseBody
    public String sendMessageToUser(@RequestParam(value = "receiveUserId") String receiveUserId,
                                    @RequestParam(value = "message") String message) {
        try {
            SocketUsersHandler.sendMessageToUser(receiveUserId, message);
            return "message send success!";
        } catch (RuntimeException exp) {
            String errorMessage = "send message error,please check!";
            log.error(errorMessage, exp);
            return "message send error!";
        }
    }


    /***
     * <p>
     *     获取socket会话链接地址
     * </p>
     *
     * @param userId 连接时当前登录用户的用户id
     * @author feilong
     * @version 1.0
     * @return socket链接地址
     */
    @GetMapping("/getSocketUrl")
    public String getSocketUrl(
            @RequestParam(value = "userId") String userId) {
        try {
            if (StringUtils.isEmpty(userId)) {
                String errorMessage = "parameter userid must pass,please check!";
                log.error(errorMessage);
                throw new IllegalArgumentException(errorMessage);
            }
            String socketConnectUrl =
                    socketConfigProperties.
                            getSocketConnectUrl() +
                            SocketConstants.MESSAGE_SERVICE_URL + "?userid=" + userId;
            return socketConnectUrl;
        } catch (RuntimeException exp) {
            String errorMessage = "request error,please check!";
            log.error(errorMessage, exp);
            return errorMessage;
        }
    }

    /**
     * 定时推送消息
     */
    @Scheduled(fixedRate = 1000)
    public void callback() {
        // 发现消息
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        messagingTemplate.convertAndSend("/topic/callback", "定时推送消息时间: " + df.format(new Date()));
    }
}
